﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;

using mvcForum.Core;

using mvcForum.Web.Extensions;
using mvcForum.Core.Specifications;
using mvcForum.Core.Abstractions.Interfaces;
using mvcForum.Core.Configuration;

namespace mvcForum.Web.ViewModels {

	public class ForumViewModel : ForumViewModelBase {

		public ForumViewModel() { }

		public ForumViewModel(Forum forum, Int32 topicsPerPage, AdminAuthorNameSetting authorSetting) {
			this.Id = forum.Id;
			this.Name = forum.Name;
			this.SortOrder = forum.SortOrder;
			this.Posts = forum.PostCount;
			this.Description = forum.Description;

			this.Paging = new PagingModel();
			this.Paging.Count = forum.TopicCount;
			IEnumerable<Topic> visibleTopics = forum.Topics.AsQueryable().Where(new TopicSpecifications.Visible().IsSatisfied);
			Int32 announcements = visibleTopics.Where(t => t.TypeValue == (Int32)TopicType.Announcement).Count();
			this.Paging.ActualCount = visibleTopics.Count();
			Int32 actualPerPageCount = topicsPerPage - announcements;
			if (actualPerPageCount > 0) {
				this.Paging.Pages = (Int32)Math.Ceiling((Decimal)(this.Paging.ActualCount - announcements) / (Decimal)actualPerPageCount);
				if (this.Paging.Pages < 1) {
					this.Paging.Pages = 1;
				}
			}

			if (forum.LastPost != null) {
				this.LastPosted = forum.LastPosted;
				this.AuthorId = forum.LastPostUser.Id;
				this.LastUsername = this.Author = forum.LastPostUser.AuthorName(authorSetting);
				//this.LastUsername = forum.LastPostUsername;
				this.LastTopicTitle = forum.LastTopic.Title;
				this.LastTopicId = forum.LastTopic.Id;
			}

			this.Following = forum.Following();
			this.Access = forum.GetAccess();
			this.Unread = (this.Authenticated ? (forum.LastPost != null && forum.LastRead() < forum.LastPosted.Value && forum.LastPostUser.Id != this.CurrentUser.Id) : false);
		}

		public PagingModel Paging { get; set; }

		private AccessFlag Access { get; set; }
		public bool IsModerator {
			get {
				return this.HasAccess(AccessFlag.Moderator);
			}
		}

		public bool Accessible {
			get {
				return this.HasAccess(AccessFlag.Read);
			}
		}

		public bool CanUpload {
			get {
				return this.HasAccess(AccessFlag.Upload);
			}
		}

		public bool CanPost {
			get {
				return this.HasAccess(AccessFlag.Post);
			}
		}

		private bool HasAccess(AccessFlag flag) {
			return (this.Access & flag) == flag;
		}

		public Int32 Id { get; private set; }
		[Required]
		public String Name { get; private set; }
		[Required]
		public Int32 SortOrder { get; private set; }
		[Required]
		public String Description { get; private set; }

		public Boolean Following { get; set; }
		public Boolean Unread { get; private set; }
		public Int32 Posts { get; private set; }
		//public int TopicCount { get; private set; }
		//public Int32 ActualTopicCount { get; private set; }
		//public int PerPageCount { get; private set; }
		//public int Page { get; set; }
		//public int Pages { get; private set; }
		public DateTimeOffset? LastPosted { get; private set; }
		public String LastUsername { get; private set; }
		public String LastTopicTitle { get; private set; }
		public Int32? LastTopicId { get; private set; }
		public Int32? AuthorId { get; private set; }
		public String Author { get; private set; }
	
		public CategoryViewModel Category { get; set; }
		public ForumViewModel Parent { get; set; }
		public IEnumerable<ForumViewModel> SubForums { get; set; }
		public IEnumerable<TopicViewModel> Topics { get; set; }
		public ReadOnlyCollection<ForumAccessViewModel> ForumAccesses { get; set; }
		public ReadOnlyCollection<GroupViewModel> Groups { get; set; }
	}
}